package com.readystatesoftware.maps;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class TapControlledMapView extends MapView implements OnGestureListener {

	private GestureDetector gd;

	private GeoPoint mOldTopLeft;
	private GeoPoint mOldCenter;
	private GeoPoint mOldBottomRight;
	private int mOldZoomLevel = -1;

	private MapViewListener mMapViewListener;

	public MapViewListener getMapViewListener() {
		return mMapViewListener;
	}

	public void setMapViewListener(MapViewListener value) {
		mMapViewListener = value;
	}

	private OnSingleTapListener singleTapListener;

	public TapControlledMapView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setupGestures();
	}

	public TapControlledMapView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
		setupGestures();
	}

	public TapControlledMapView(Context context, String apiKey) {
		super(context, apiKey);
		setupGestures();
	}

	private void setupGestures() {
		gd = new GestureDetector(this);

		// set the on Double tap listener
		gd.setOnDoubleTapListener(new OnDoubleTapListener() {

			public boolean onSingleTapConfirmed(MotionEvent e) {
				if (singleTapListener != null) {
					return singleTapListener.onSingleTap(e);
				} else {
					return false;
				}
			}

			public boolean onDoubleTap(MotionEvent e) {
				TapControlledMapView.this.getController().zoomInFixing(
						(int) e.getX(), (int) e.getY());
				return false;
			}

			public boolean onDoubleTapEvent(MotionEvent e) {
				return false;
			}

		});
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (this.gd.onTouchEvent(ev)) {
			return true;
		} else {
			return super.onTouchEvent(ev);
		}
	}

	public void setOnSingleTapListener(OnSingleTapListener singleTapListener) {
		this.singleTapListener = singleTapListener;
	}

	public boolean onDown(MotionEvent e) {
		return false;
	}

	public void onShowPress(MotionEvent e) {
	}

	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}

	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		return false;
	}

	public void onLongPress(MotionEvent e) {
	}

	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		return false;
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);

		GeoPoint newCenter = this.getMapCenter();
		GeoPoint newTopLeft = this.getProjection().fromPixels(0, 0);
		GeoPoint newBottomRight = this.getProjection().fromPixels(
				this.getWidth(), this.getHeight());
		int newZoomLevel = this.getZoomLevel();

		if (mOldCenter == null)
			mOldCenter = newCenter;

		if (mOldTopLeft == null)
			mOldTopLeft = newTopLeft;

		if (mOldBottomRight == null)
			mOldBottomRight = newBottomRight;

		if (newTopLeft.getLatitudeE6() != mOldTopLeft.getLatitudeE6()
				|| newTopLeft.getLongitudeE6() != mOldTopLeft.getLongitudeE6()) {
			if (this.mMapViewListener != null) {
				GeoPoint oldTopLeft, oldCenter, oldBottomRight;

				oldTopLeft = mOldTopLeft;
				oldCenter = mOldCenter;
				oldBottomRight = mOldBottomRight;

				mOldBottomRight = newBottomRight;
				mOldTopLeft = newTopLeft;
				mOldCenter = newCenter;

				mMapViewListener.onPan(oldTopLeft, oldCenter, oldBottomRight,
						newTopLeft, newCenter, newBottomRight);
			}
		}

	
		if (mOldZoomLevel != newZoomLevel && mMapViewListener != null) {
			int oldZoomLevel = mOldZoomLevel;
			GeoPoint oldTopLeft, oldCenter, oldBottomRight;
			oldTopLeft = mOldTopLeft;
			oldCenter = mOldCenter;
			oldBottomRight = mOldBottomRight;

			mOldZoomLevel = newZoomLevel;
			mOldBottomRight = newBottomRight;
			mOldTopLeft = newTopLeft;
			mOldCenter = newCenter;

			mMapViewListener.onZoom(oldTopLeft, oldCenter, oldBottomRight,
					newTopLeft, newCenter, newBottomRight, oldZoomLevel,
					newZoomLevel);
		}
	}
	
	public GeoPoint[] getLimits(){
		GeoPoint[] points=new GeoPoint[2];
		GeoPoint newTopLeft = this.getProjection().fromPixels(0, 0);
		GeoPoint newBottomRight = this.getProjection().fromPixels(
				this.getWidth(), this.getHeight());
		points[0]=newTopLeft;
		points[1]=newBottomRight;
		return points;
	}
	
}
